﻿<template>
  <div v-bind="$attrs">
    <template v-if="rowComponent">
      <template v-if="page.groups && groupComponent">
        <component
          :is="groupComponent"
          :groupKey="g"
          :records="page.records"
          v-for="g in page.groups"
          :key="g"
        />
      </template>
      <MyGridBox v-else ref="grid" :columns="columnsNum">
        <component
          :is="rowComponent"
          v-for="row in page.records"
          :key="row.ID"
          :row="row"
          style="width: 100%; height: 100%; box-sizing: border-box"
        />
      </MyGridBox>
    </template>

    <el-empty
      v-if="rowComponent && page.totalCount == 0"
      description="没有数据"
      style="width: 100%; padding: 10px auto 10px auto"
    />

    <el-table
      v-if="!rowComponent && cols.length > 0"
      :data="page.records"
      border
      highlight-current-row
      ref="grid"
      @selection-change="handleSelectionChange"
      @current-change="handleCurrentChange"
      v-bind="$attrs"
      @sort-change="handleSortChange"
      @row-dblclick="onRowDbClick"
      :summary-method="getSummaries"
      :show-summary="isShowSum"
      @row-click="onRowClick"
      :row-key="rowKey2"
      lazy
      :row-style="getRowStyle"
      :tree-props="tree"
      :load="loadTree"
      :span-method="spanMethod"
      :default-sort="defaultSort"
    >
      <el-table-column
        v-if="multi"
        type="selection"
        width="50"
        :selectable="allowSelectable"
        align="center"
      ></el-table-column>
      <template v-for="col in cols" :key="col">
        <el-table-column v-if="col.expand" type="expand" :prop="col.code">
          <template #default="scope">
            <component
              :is="col.expand.control"
              v-model="scope.row[col.code]"
              :disabled="true"
              v-bind="col.expand.props"
              :formData="scope.row"
            />
          </template>
        </el-table-column>

        <el-table-column
          v-else-if="col.tpl"
          :prop="col.code"
          :label="col.label"
          header-align="center"
          :formatter="formatCol"
          :sortable="getSort(col)"
          :show-overflow-tooltip="getOverflowTooltip(col)"
          :width="getWidth(col)"
          :align="getAlign(col)"
        >
          <template #default="scope">
            <component
              :is="col.tpl.control"
              v-model="scope.row[col.code]"
              :disabled="getTplDisabled(col, scope.row)"
              :options="col.options"
              v-bind="col.tpl.props"
              :formData="scope.row"
            />
          </template>
        </el-table-column>

        <el-table-column
          v-else-if="col.control == 'MyCheckGroup'"
          :prop="col.code"
          :label="col.label"
          header-align="center"
          :formatter="formatCol"
          :sortable="getSort(col)"
          :show-overflow-tooltip="getOverflowTooltip(col)"
          :width="getWidth(col)"
          :align="getAlign(col)"
        >
          <template #default="scope">
            <MyCheckGroup
              v-model="scope.row[col.code]"
              :disabled="true"
              v-bind="col['MyCheckGroup']"
            />
          </template>
        </el-table-column>

        <el-table-column
          v-else-if="col.children"
          :label="col.label"
          header-align="center"
        >
          <template v-for="c1 in col.children" :key="c1">
            <el-table-column
              :prop="c1.code"
              :label="c1.grid_label || c1.label"
              header-align="center"
              :formatter="formatCol"
              :sortable="getSort(c1)"
              :show-overflow-tooltip="getOverflowTooltip(c1)"
              :width="getWidth(c1)"
              :align="getAlign(c1)"
            >
              <template #default="scope" v-if="c1.tpl">
                <component
                  :is="c1.tpl.control"
                  :disabled="disabled"
                  v-model="scope.row[c1.code]"
                  v-bind="c1.tpl['props']"
                  :formData="scope.row"
                />
              </template>
            </el-table-column>
          </template>
        </el-table-column>
        <el-table-column
          v-else-if="
            col.control == 'photo' ||
            col.control == 'HandWriteBoard' ||
            col.control == 'sign' ||
            col.control == 'MultiSign'
          "
          :prop="col.code"
          :label="col.label"
          :width="getWidth(col)"
          align="center"
          header-align="center"
        >
          <template #default="scope">
            <ElImage
              v-for="(item, ix) in getPhotos(scope.row, col.code, col)"
              :key="item"
              fit="contain"
              :src="item"
              :preview-src-list="getPhotos(scope.row, col.code, col, true)"
              :initial-index="ix"
              :style="{
                width: getPhotoWidth(col) + 'px',
                height: getPhotoHeight(col) + 'px',
              }"
            ></ElImage>
          </template>
        </el-table-column>
        <el-table-column
          v-else-if="col.control == 'file'"
          :prop="col.code"
          :label="col.label"
          :width="getWidth(col)"
          align="center"
          header-align="center"
        >
          <template #default="scope">
            <el-dropdown v-if="scope.row[col.code]" @command="downloadFile">
              <span class="el-dropdown-link">
                文件下载
                <el-icon class="el-icon--right">
                  <arrow-down />
                </el-icon>
              </span>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item
                    v-for="(item, ix) in getFiles(
                      scope.row,
                      col.code,
                      scope.column
                    )"
                    :key="ix"
                    :command="item"
                    >{{ item.name }}</el-dropdown-item
                  >
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </template>
        </el-table-column>
        <el-table-column
          v-else-if="col.control == 'check' || col.type == 'boolean'"
          :prop="col.code"
          :label="col.label"
          :width="getWidth(col)"
          align="center"
          header-align="center"
        >
          <template #default="scope">
            <template
              v-if="
                col.type == 'boolean' || typeof scope.row[col.code] == 'boolean'
              "
            >
              <el-icon>
                <Select v-if="scope.row[col.code] == true" />
                <CloseBold v-if="scope.row[col.code] == false" />
              </el-icon>
            </template>
            <span v-else>{{ scope.row[col.code] }}</span>
          </template>
        </el-table-column>
        <el-table-column
          v-else-if="col.control == 'action'"
          :label="col.label"
          :width="getWidth(col)"
          align="center"
        >
          <template #default="scope">
            <template v-for="ac in col.actions" :key="ac">
              <el-button
                type="text"
                text
                v-if="doIf(ac.vif, scope.row)"
                @click="doColAction(ac.click, scope.row)"
                >{{ getActioLabel(ac, scope.row) }}</el-button
              >
            </template>
          </template>
        </el-table-column>
        <el-table-column
          v-else
          :prop="col.code"
          :label="col.label"
          header-align="center"
          :formatter="formatCol"
          :sortable="getSort(col)"
          :show-overflow-tooltip="getOverflowTooltip(col)"
          :width="getWidth(col)"
          :align="getAlign(col)"
        >
        </el-table-column>
      </template>
      <el-table-column
        label="操作"
        :width="actionWidth2"
        v-if="
          selectModel != true &&
          actionWidth2 > 0 &&
          (rowActions.length > 0 || $slots.action)
        "
        align="center"
        header-align="center"
      >
        <template #default="scope">
          <MyGridSpace spacer="|" wrap>
            <template v-for="ac in rowActions" :key="ac">
              <el-link
                type="primary"
                v-if="doIf(ac.vif, scope.row)"
                @click="doColAction(ac.click, scope.row)"
                >{{ getActioLabel(ac, scope.row) }}</el-link
              >
            </template>

            <slot name="action" :row="scope.row"></slot>
          </MyGridSpace>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      style="margin-top: 8px; padding-top: 8px; border-top: 1px solid #ccc"
      v-if="page.pageCount > 1"
      :layout="$mbh5 ? pageLayoutH5 : pageLayout"
      background
      v-model:current-page="page.pageIndex"
      v-model:page-size="page.pageSize"
      :page-sizes="pageSizes"
      :total="page.totalCount"
      :pageCount="page.pageCount"
    ></el-pagination>
  </div>
</template>

<script>
import mydt from "./mydate";
import Utils from "./Utils";
import store from "./store";
import Server from "./Server";

import { CloseBold, Select } from "@element-plus/icons-vue";
import { ElLink, timeSelectProps } from "element-plus";
import { toRaw, computed } from "vue";
import MyGridSpace from "./MyGridSpace";

export default {
  name: "MyGrid",
  emits: [
    "selected",
    "update:search",
    "afterLoadCfg",
    "currentChanged",
    "update:modelValue",
    "loadedData",
  ],
  components: { CloseBold, Select, ElLink, MyGridSpace },
  props: {
    modelValue: Array,
    tbname: String,
    search: {
      type: Object,
      default: {},
    },
    pformSearch: Object, //父亲form传来的过滤条件
    multi: Boolean,
    fields: String, //需要显示的字段名称，为空则显示全部
    disabled: Boolean,
    actionWidth: {
      type: [String, Number],
      default: "120px",
    },
    formData: Object,
    pageLayout: {
      type: String,
      default: "total, sizes,prev, pager, next,jumper",
    },
    pageLayoutH5: {
      type: String,
      default: "prev, pager, next",
    },
    selectModel: Boolean, //用于选择模式，action栏不显示
  },
  inject: {
    MyListPage: { default: null },
  },
  data() {
    return {
      pageSizes: [10, 20, 50, 100, 200],
      cfg: {
        name: "",
        action: "",
        param: "",
        columns: [],
      },
      cols: [],
      page: {
        pageIndex: 1,
        pageSize: 10,
        pageCount: 0,
        totalCount: 0,
        records: [],
      },
      multipleSelection: [],
      currentRow: null,
      tree: null,
      defaultSort: { prop: "", order: "" },
      rowComponent: null,
      groupComponent: null,
      columnsNum: 10,
      tbSearch: {}, //tb定义上自带的search条件，默认值
    };
  },
  created() {
    try {
      this.loadCfg();
    } catch (e) {
      console.log(e);
    }
  },
  methods: {
    //计算合并行的回调
    spanMethod({ row, column, rowIndex, columnIndex }) {
      if (this.rowspans) {
        let rowspan = this.rowspans[rowIndex][columnIndex];
        if (rowspan < 0) {
          rowspan = 0 - rowspan;
        }
        return [rowspan, 1];
      }
      return [1, 1];
    },
    allowSelectable(row, index) {
      let val = this.doIf("allowSelectRow", row);
      return val;
    },
    loadTree(row, treeNode, resolve) {
      if (this.tree) {
        if (this.tree.load) {
          let el = this.$refs.grid ? this.$refs.grid.$el : null;
          this.tree.load(row, treeNode, resolve, this.search, el);
        } else if (this.tree.action) {
          let idfield = this.tree.id || "id" in row ? "id" : "ID";
          let pm = { id: row[idfield] };
          Server.call(this.tree.action, pm).then((res) => {
            resolve(res);
          });
        }
      }
    },
    getSummaries(param) {
      try {
        const { columns, data } = param;
        const sums = [];
        const me = this;
        columns.forEach((column, index) => {
          if (index === 0) {
            sums[index] = "合计";
            return;
          }
          const key = column.property;
          if (me.page.sumRow && key in me.page.sumRow) {
            sums[index] = me.page.sumRow[key];
          } else {
            sums[index] = "";
          }
        });
        return sums;
      } catch (e) {
        console.log(e);
      }
    },
    viewImg(url) {},
    proceParenFormSearch() {
      let nn = {};
      let hasChange = false;
      if (this.pformSearch && this.formData) {
        Object.keys(this.pformSearch).map((p) => {
          let v = this.pformSearch[p];
          if (v) {
            nn[p] = this.formData[v];
            hasChange = true;
          }
        });
      }
      if (hasChange) {
        let pp = { ...this.search, ...nn };
        this.$emit("update:search", pp);
      }
      this.$emit("afterLoadCfg", this);
      if (this.tbname && this.search) {
        this.loadData(1);
      }
    },

    loadCfg() {
      if (this.tbname == "") return;
      return this.$server.getDM(this.tbname).then((cfg) => {
        this.cfg = cfg;
        this.rebuildCols();
        this.proceParenFormSearch();
      });
    },

    rebuildCols() {
      this.tbSearch = {};

      this.rowComponent = computed(() => this.cfg?.grid?.rowComponent);
      this.groupComponent = computed(() => this.cfg?.grid?.groupComponent);
      this.columnsNum = computed(() => this.cfg?.grid?.columnsNum || 10);

      Utils.getTbSearchFields(this.cfg, this.tbSearch);

      if (
        this.cfg.grid &&
        this.cfg.grid.pageSize &&
        this.cfg.grid.pageSize > 10
      ) {
        this.page.pageSize = this.cfg.grid.pageSize;
        if (this.pageSizes.indexOf(this.page.pageSize) == -1) {
          this.pageSizes.push(this.page.pageSize);
        }
      }
      try {
        this.tree = this.cfg.grid.tree;
        this.prepareCols();
      } catch (e) {
        console.log(e);
      }
    },

    //重新加载该行的下级字节点
    reloadNodeTree(prow, pId) {
      //因为没有公开的重载下级节点的方法
      //直接修改ElementUI Table组件中treeData的数据， 后面版本可能受影响，
      var pnode = this.$refs.grid.store.states.treeData.value[pId];
      if (pnode && prow) {
        pnode.children = [];
        pnode.loaded = false;
        this.$refs.grid.store.loadOrToggle(prow);
        return true;
      }
      return false;
    },

    loadData(pageIndex, moreSearch, row) {
      if (this.tree && row) {
        //树节点变化以后，不用重载整个表格的数据， 重新加载父节点的数据即可
        let pidField = this.tree.pid || ("pid" in row ? "pid" : "PID");
        let idField = this.tree.id || ("id" in row ? "id" : "ID");
        let pid = row[pidField];
        if (pid) {
          let prow = this.page.records.find((p) => p[idField] == pid);
          if (prow) {
            return this.reloadNodeTree(prow, pid);
          }
        }
      }
      pageIndex = pageIndex || this.page.pageIndex;

      moreSearch = moreSearch
        ? { ...this.tbSearch, ...this.search, ...moreSearch }
        : { ...this.tbSearch, ...this.search };
      let el = this.$refs.grid ? this.$refs.grid.$el : null;

      let pageSize2 = parseInt(this.page.pageSize);
      let pmObj = { ...moreSearch };
      moreSearch = { ...pmObj };
      pmObj.tbname = this.tbname;
      pmObj.pageIndex = pageIndex;
      pmObj.pageSize = pageSize2;

      let _call_dt = new Date().getTime();

      if (
        this._last_pmObj &&
        Utils.shallowEqual(this._last_pmObj, pmObj) &&
        _call_dt - this._last_call_dt < 500
      ) {
        return new Promise((resove, reject) => resove());
      }

      this._last_pmObj = pmObj;
      this._last_call_dt = _call_dt;

      return this.$server
        .list(this.tbname, pageIndex, pageSize2, moreSearch, el)
        .then((res) => {
          //页面初始化的时候可能调用了一次，其它情况（tree初始化的时候又调用了一次），但是返回顺序不一致
          //只接收最后一次调用的返回值
          if (_call_dt != this._last_call_dt) return;
          if (Array.isArray(res)) {
            res = {
              pageIndex: 1,
              pageSize: 10000,
              pageCount: 1,
              totalCount: res.length,
              records: res,
            };
          }
          this.page.records = [];
          res.pageSize = this.page.pageSize;
          if (
            this.cfg.grid &&
            this.cfg.grid.methods &&
            this.cfg.grid.methods.onLoaded &&
            typeof this.cfg.grid.methods.onLoaded == "function"
          ) {
            this.cfg.grid.methods.onLoaded.apply(this, [res]);
          }

          this.page = res;
          this.$emit("loadedData", this.page);
        });
    },

    getActioLabel(ac, row) {
      try {
        if (typeof ac.label == "string") {
          return ac.label;
        } else if (typeof ac.label == "function") {
          return ac.label.apply(this, [row]);
        }
      } catch {}
      return "无名";
    },

    getAlign(col) {
      if (col.align) return col.align;

      switch (col.control) {
        case "combo":
        case "radio":
        case "check":
          return "center";
      }
      switch (col.type) {
        case "int":
        case "number":
          return "right";
        case "boolean":
        case "bool":
        case "boolean":
          return "center";
      }
      return "left";
    },
    getSort(col) {
      if (col.sort_field || col.sortable) {
        return "custom";
      }
      return false;
    },
    getComboLabel(value, options) {
      if (!options) return value;
      var item = options.filter((p) => p.value == value);
      if (item.length == 1) {
        return item[0].label;
      }
      return value;
    },
    formatCol(row, column, cellValue, index) {
      if (cellValue == undefined) return "";
      if (!column.col) {
        column.col = this.cfg.columns.filter(
          (p) => p.code == column.property
        )[0];
      }
      var col = column.col;

      if (col.control == "combo" || col.options) {
        let label = this.getComboLabel(cellValue, col.options);
        return label;
      }
      if (col.format) {
        switch (col.type) {
          case "date":
          case "time":
          case "datetime":
            return mydt.formatDate(cellValue, col.format);
        }
        if (typeof col.format == "function") {
          return col.format.apply(this, [cellValue, col, row]);
        }
      } else {
        switch (col.type) {
          case "date":
            return mydt.formatDate(cellValue, "yyyy-MM-dd");
          case "time":
            return mydt.formatDate(cellValue, "HH:II");
          case "datetime":
            return mydt.formatDate(cellValue, "yyyy-MM-dd HH:II");
        }
      }
      return cellValue;
    },
    getOverflowTooltip(col) {
      return (
        col.control == "text" ||
        col.control == "textarea" ||
        col.control == "addr"
      );
    },
    getWidth(col) {
      if (col.width >= 0) {
        return col.width;
      }
      return null;
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    handleCurrentChange(row) {
      //this.currentRow = row;
      //this.$emit("currentChanged", row, this);
    },
    handleSortChange({ column, prop, order }) {
      let sorder = "";
      var col = this.findCol(prop);
      if (col) {
        let field = col.sort_field || col.code;
        if (order) {
          if (order == "ascending") {
            sorder = `${field} ASC`;
          } else {
            sorder = `${field} DESC`;
          }
        }

        localStorage.setItem(`${this.tbname}_sort`, sorder);
        let vsear = {
          ...this.search,
          order: sorder,
          SortField: field,
          SortType: order == "ascending" ? 1 : 2, //为了兼容form2Api
        };
        this.$emit("update:search", vsear);
      }
    },
    getSelected() {
      if (this.multi) {
        return this.multipleSelection;
      }
      return this.currentRow ? [this.currentRow] : [];
    },
    clearSelection() {
      if (this.$refs.grid && this.$refs.grid.clearSelection) {
        this.$refs.grid.clearSelection();
      }
    },
    onRowDbClick(row, column, event) {
      this.$emit("selected", row, this);
    },
    onRowClick(row, column, event) {
      this.currentRow = row;
      if (this.allowSelectable(row)) {
        this.$refs.grid.toggleRowSelection(row, true);
        this.$refs.grid.setCurrentRow(row);
      }
    },
    prepareCols() {
      //grid: "Photo:64,ClassName:100,LoginName:120,个人资料:[Name:120;Gender:50;BirthDate:120],JoinDate:120,TeachDate:120,Post,TeacherRole,Telephone:120,Specialty,SchoolStatus:100,Status:60",
      //字段名，字段名:width, 分组名:[字段名;字段名：width]
      var items = [];
      let fields = this.fields || this.cfg.grid.fields || this.cfg.grid;
      //如果有定义动态列方法
      if (typeof fields == "function") {
        fields = fields.apply(this, [this.cfg, fields]);
      }
      var disFields = fields.split(/,/g).filter((p) => p != "");
      for (var i = 0; i < disFields.length; i++) {
        var item = disFields[i];
        var ix = item.indexOf(":");
        if (ix > 0) {
          if (item.indexOf("[") > 0) {
            var group = {
              code: `group_${i}`,
              label: item.substr(0, ix),
              children: [],
            };
            items.push(group);
            var str = item.substr(ix + 2, item.length - ix - 3);
            var kk = str.split(";");
            for (var i1 = 0; i1 < kk.length; i1++) {
              var kk1 = kk[i1].split(":");
              var col = null;
              if (kk1.length > 1) {
                //数值是宽度，否则是label
                let lw = kk1[1];
                let lwtp = typeof parseInt(lw);
                if (lwtp == "number") {
                  col = this.findCol(kk1[0], kk1[1]);
                } else {
                  col = this.findCol(kk1[0]);
                  col.grid_label = col.grid_label || kk1[1];
                }
              } else {
                col = this.findCol(kk1[0]);
              }
              if (col != null) {
                if (col.label.startsWith(group.label)) {
                  col.grid_label =
                    col.grid_label || col.label.substr(group.label.length);
                }
                group.children.push(col);
              }
            }
          } else {
            items.push(this.findCol(item.substr(0, ix), item.substr(ix + 1)));
          }
        } else {
          items.push(this.findCol(item));
        }
      }
      this.cols = items.filter((x) => !!x);
    },
    findCol(code, width) {
      var col = this.cfg.columns.filter((p) => p.code == code)[0];
      if (col && width) {
        col.width = width;
      }
      return col;
    },
    getFiles(row, code, col) {
      let val = row[code];
      if (!val) return [];

      let fs = val.split(";").map((p) => {
        let f = p.split(":");
        if (f.length > 1) {
          return { name: f[1], path: store.getUrl(f[0]) };
        } else {
          let pp = p.splice("/");
          return { name: pp[pp.length - 1], path: store.getUrl(p) };
        }
      });
      return fs;
    },
    getPhotos(row, code, col, getAll) {
      let list = (row[code] || "").split(";").filter((p) => p != "");

      let max = 1;
      let prop = col["photo"];
      if (prop && prop.grid_col && typeof prop.grid_col == "number") {
        max = prop.grid_col;
      }
      if (!getAll) {
        if (list.length > max) {
          list.splice(max);
        }
      }
      let nitems = list.map(store.getUrl);
      return nitems;
    },
    getPhotoShape(col) {
      let prop = col["photo"];
      if (prop && prop.shape) {
        return prop.shape;
      }
      return "circle";
    },
    getPhotoWidth(col) {
      let prop = col["photo"];
      if (prop) {
        return prop.width || prop.size || 32;
      }
      return 32;
    },
    getPhotoHeight(col) {
      let prop = col["photo"];
      if (prop && prop.size) {
        return prop.height || prop.size || 32;
      }
      return 32;
    },
    getCusMethod(key) {
      return (
        Utils.getValByKey(this.cfg, `grid.methods.${key}`) ||
        Utils.getValByKey(this.cfg, `ext.common.methods.${key}`)
      );
    },
    doIf(vif, row) {
      if (!vif) {
        return true;
      }
      if (typeof vif == "string") {
        vif = this.getCusMethod(vif);
      }
      if (typeof vif == "function") {
        return vif.apply(this, [row]);
      }
      vif = this[vif];
      if (typeof vif == "function") {
        return vif.apply(this, [row]);
      }
      return true;
    },
    doColAction(fun, row) {
      let funName = "";
      if (typeof fun == "string") {
        funName = fun;
        fun = this.getCusMethod(funName);
      }
      if (typeof fun == "function") {
        fun.apply(this, [row, this, this.MyPage]);
      } else {
        $msg.error("找不到自定义方法：" + funName);
      }
    },
    getRowStyle(row) {
      if (this.tree && row == this.$refs.grid.setCurrentRow()) {
        return "myselected";
      }
      return null;
    },
    downloadFile(fileItem) {
      Server.downloadFile(fileItem.path, fileItem.name);
    },
    getTplDisabled(col, row) {
      if (this.disabled) return true;

      if (typeof col.tpl.disabled == "function") {
        return col.tpl.disabled.apply(this, [row]);
      }
      return col.tpl.disabled;
    },
  },

  watch: {
    tbname() {
      this.loadCfg();
    },
    search(val, old) {
      this.tbSearch = { ...val };
      if (JSON.stringify(val) != JSON.stringify(old)) {
        if (val.order && typeof val.order == "string") {
          let sorder = val.order;
          if (sorder) {
            let _sorder = sorder.split(" ");
            this.defaultSort = {
              prop: _sorder[0],
              order: _sorder[1] == "DESC" ? "descending" : "ascending",
            };
          } else {
            this.defaultSort = null;
          }
        }
        this.loadData(1);
      }
    },
    formData() {
      this.proceParenFormSearch();
    },
    "page.pageIndex": function () {
      this.loadData();
    },
    "page.pageSize": function () {
      this.loadData(1);
    },
    fields() {
      this.prepareCols();
    },
  },
  computed: {
    rowspans() {
      if (
        this.rowComponent ||
        this.cols.length == 0 ||
        this.page.records.length < 2 ||
        !this.cfg?.grid?.rowspans ||
        !Array.isArray(this.cfg.grid.rowspans)
      ) {
        return null;
      }
      var cols = this.cols;
      const its = this.page.records;
      //加1列,操作列
      const rets = Array(its.length)
        .fill()
        .map(() => Array(cols.length + 1).fill(1));
      this.cfg.grid.rowspans.forEach((ixCol) => {
        let lastVal = "";
        let lastIx = 0;

        for (var i = 0; i < its.length; i++) {
          var row = its[i];
          var val = row[cols[ixCol].code];

          rets[i][ixCol] = 0;
          if (val != lastVal || (ixCol > 0 && rets[i][ixCol - 1] < 0)) {
            rets[lastIx][ixCol] = 0 - (i - lastIx);
            lastIx = i;
            lastVal = val;
          }
        }
        if (lastIx < its.length) {
          rets[lastIx][ixCol] = 0 - (its.length - lastIx);
        }
      });
      return rets;
    },
    isShowSum() {
      let v = this.page.sumRow != null;
      return v;
    },
    actionWidth2() {
      if (typeof this.cfg.grid == "object" && "actionWidth" in this.cfg.grid) {
        return this.cfg.grid.actionWidth;
      }
      return this.actionWidth;
    },
    rowActions() {
      if (typeof this.cfg.grid == "object") {
        return this.cfg.grid.actions || [];
      }
      return [];
    },
    rowKey2() {
      let c = this.findCol("id");
      if (c) return "id";
      if (this.tree && this.tree.id) {
        return this.tree.id;
      }
      return "ID";
    },
  },
};
</script>

<style scoped>
.line2 {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.myselected {
  background-color: rgb(89, 76, 207);
}
</style>

<style>
.el-table .cell {
  white-space: nowrap;
}

.el-table th .cell {
  white-space: normal !important;
  word-wrap: break-word;
  word-break: break-word;
}
</style>
